package ru.myrtle.umf.impl;

import java.util.*;
import ru.myrtle.umf.*;
import ru.myrtle.umf.util.*;

public class UPackageOperations extends UPackageOperationsStub  {

    private static class Chooser implements UPredicate<UClassifier> {

        private final UClass type;

        private Chooser(UClass type) {
            this.type = type;
        }

        @Override
        public boolean evaluate(UClassifier object) {
            return object.uClass() == type;
        }
    }

    /*
     *
     */

    private static class Caster<Type extends UClassifier> implements UTransformer<UClassifier, Type> {

        private final Class<Type> type;

        private Caster(Class<Type> type) {
            this.type = type;
        }

        @Override
        public Type transform(UClassifier source) {
            return type.cast(source);
        }
    }

    /*
     *
     */

    private static final Chooser CHOOSER_CLASS = new Chooser(UModel.UCLASS);
    private static final Chooser CHOOSER_DATA_TYPE = new Chooser(UModel.UDATA_TYPE);
    private static final Chooser CHOOSER_ENUMERATION = new Chooser(UModel.UENUMERATION);

    private static final Caster<UClass> CASTER_CLASS = new Caster<UClass>(UClass.class);
    private static final Caster<UDataType> CASTER_DATA_TYPE = new Caster<UDataType>(UDataType.class);
    private static final Caster<UEnumeration> CASTER_ENUMERATION = new Caster<UEnumeration>(UEnumeration.class);

    /*
     *
     */

    private <Type extends UClassifier> UList<Type> select(UPackage self, Chooser chooser, Caster<Type> caster) {
        UList<Type> selected = new UObjectList<Type>();

        UUtilities.select(
                selected, self.getClassifiers(), chooser, caster
        );

        return UUtilities.unmodifiableUList(selected);
    }

    /*
     *
     */

    @Override
    public UList<UClass> getClasses(UPackage self) {
        return select(self, CHOOSER_CLASS, CASTER_CLASS);
    }

    @Override
    public boolean isSetClasses(UPackage self) {
        return true;
    }

    @Override
    public UList<UDataType> getDataTypes(UPackage self) {
        return select(self, CHOOSER_DATA_TYPE, CASTER_DATA_TYPE);
    }

    @Override
    public boolean isSetDataTypes(UPackage self) {
        return true;
    }

    @Override
    public UList<UEnumeration> getEnumerations(UPackage self) {
        return select(self, CHOOSER_ENUMERATION, CASTER_ENUMERATION);
    }

    @Override
    public boolean isSetEnumerations(UPackage self) {
        return true;
    }

}
